package com.drink.yan.svc.service;

import com.alibaba.fastjson.JSONObject;
import com.alicp.jetcache.anno.Cached;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.drink.yan.core.mapper.YanBachelorSpecialMapper;
import com.drink.yan.core.mapper.YanMasterSpecialMapper;
import com.drink.yan.core.mapper.YanSpecialGjxMapper;
import com.drink.yan.intf.entity.YanBachelorSpecial;
import com.drink.yan.intf.entity.YanMasterSpecial;
import com.drink.yan.intf.entity.YanSpecialGjx;
import com.drink.yan.intf.entity.io.SpeWorkDetailIo;
import com.drink.yan.intf.entity.io.SpecialLevelIo;
import com.drink.yan.intf.vo.SchoolSpeTreeVo;
import com.drink.yan.intf.vo.YanMasterSpecialVo;
import com.drink.yan.web.rest.req.qry.PageSchoolQry;
import com.drink.yan.web.rest.req.qry.ListMasterSpeQry;
import com.drink.yan.web.rest.req.qry.SpecialGjxQry;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * java类简单作用描述
 *
 * @Title:
 * @Package: com.drink.yan.svc.service.
 * @Author: M.simple
 * @Remark: The modified content
 * @CreateDate: 2023-12-03 23:48
 * @Version: v2.0
 */
@Service
public class SpecialService extends ServiceImpl<YanMasterSpecialMapper, YanMasterSpecial> {

	@Resource
	private YanSpecialGjxMapper yanSpecialGjxMapper;

	@Resource
	private YanBachelorSpecialMapper yanBachelorSpecialMapper;

	public YanBachelorSpecial bachelorSecialDetail(String specialCode) {

		LambdaQueryWrapper<YanBachelorSpecial> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(YanBachelorSpecial::getSpecialCode, specialCode);
		return (YanBachelorSpecial) this.yanBachelorSpecialMapper.selectOne(wrapper);
	}

	public YanMasterSpecialVo specialDetail(String specialCode) {

		LambdaQueryWrapper<YanMasterSpecial> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(YanMasterSpecial::getSpecialCode, specialCode);
		wrapper.last("limit 1");
		YanMasterSpecial yanMasterSpecial = this.baseMapper.selectOne(wrapper);
		return convertMasterSpeVo(yanMasterSpecial);
	}

	private YanMasterSpecialVo convertMasterSpeVo(YanMasterSpecial yanMasterSpecial) {

		if(Objects.isNull(yanMasterSpecial)){
			return new YanMasterSpecialVo();
		}
		YanMasterSpecialVo masterSpecialVo = yanMasterSpecial.transform(YanMasterSpecialVo.class);
		List<SpeWorkDetailIo> salaryContent = masterSpecialVo.getSalaryContent();
		if (Objects.nonNull(salaryContent) && !CollectionUtils.isEmpty(salaryContent)) {
			List<SpeWorkDetailIo> speWorkDetailIos = JSONObject.parseArray(JSONObject.toJSONString(salaryContent), SpeWorkDetailIo.class);
			BigDecimal sum = speWorkDetailIos.stream().map(SpeWorkDetailIo::getValue).reduce(BigDecimal.ZERO, BigDecimal::add);
			masterSpecialVo.setAgvSalary(sum.divide(BigDecimal.valueOf(speWorkDetailIos.size()), 2, RoundingMode.HALF_UP));
		}
		return masterSpecialVo;
	}

	public YanMasterSpecial specialDetail(Long specialId) {

		return convertMasterSpeVo(this.baseMapper.selectById(specialId));
	}

	@Cached(name = "tree:school:spe:category:", key = "#qry", expire = 600)
	public List<SchoolSpeTreeVo> listSchoolSpeCategory(PageSchoolQry qry) {

		LambdaQueryWrapper<YanMasterSpecial> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.select(YanMasterSpecial::getLevel1Code, YanMasterSpecial::getLevel1Name,
				YanMasterSpecial::getLevel2Code, YanMasterSpecial::getLevel2Name, YanMasterSpecial::getSpecialCode, YanMasterSpecial::getSpecialName);
		queryWrapper.isNotNull(YanMasterSpecial::getLevel1Code).isNotNull(YanMasterSpecial::getLevel2Code);
		queryWrapper.orderByDesc(YanMasterSpecial::getLevel1Code);
		List<YanMasterSpecial> yanSchoolRecruits = this.baseMapper.selectList(queryWrapper);
		List<SpecialLevelIo> specialLevelIos = JSONObject.parseArray(JSONObject.toJSONString(yanSchoolRecruits), SpecialLevelIo.class);
		return convertSpeTree(specialLevelIos);
	}

	@Cached(name = "tree:school:bachelor:spe:category:", key = "#qry", expire = 600)
	public List<SchoolSpeTreeVo> listBachelorSpeCategory(PageSchoolQry qry) {

		LambdaQueryWrapper<YanBachelorSpecial> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.isNotNull(YanBachelorSpecial::getLevel1Code).isNotNull(YanBachelorSpecial::getLevel2Code);
		queryWrapper.orderByDesc(YanBachelorSpecial::getLevel1Code);
		List<YanBachelorSpecial> yanSchoolRecruits = this.yanBachelorSpecialMapper.selectList(queryWrapper);
		List<SpecialLevelIo> specialLevelIos = JSONObject.parseArray(JSONObject.toJSONString(yanSchoolRecruits), SpecialLevelIo.class);
		return convertSpeTree(specialLevelIos);
	}

	/**
	 * 将平铺的专业信息，转化为Tree
	 *
	 * @param yanSchoolRecruits:
	 * @return
	 * @method convertSpeTree
	 * @author M.simple
	 * @date 2023-12-03 11:26
	 * @version v2.0
	 */
	private List<SchoolSpeTreeVo> convertSpeTree(List<SpecialLevelIo> yanSchoolRecruits) {

		List<SchoolSpeTreeVo> voArrayList = new ArrayList<>();

		Map<String, List<SpecialLevelIo>> level1 = yanSchoolRecruits.stream()
				.sorted(Comparator.comparing(SpecialLevelIo::getLevel1Code))
				.collect(Collectors.groupingBy(SpecialLevelIo::getLevel1Code, LinkedHashMap::new, Collectors.toList()));
		for (Map.Entry<String, List<SpecialLevelIo>> entry : level1.entrySet()) {
			List<SpecialLevelIo> level1Value = entry.getValue();
			if (CollectionUtils.isEmpty(level1Value)) {
				continue;
			}
			SpecialLevelIo yanMasterSpecial = level1Value.get(0);
			SchoolSpeTreeVo speTreeVo = SchoolSpeTreeVo.builder()
					.code(yanMasterSpecial.getLevel1Code())
					.name(yanMasterSpecial.getLevel1Name())
					.subTree(convertLevel2SpeTree(level1Value))
					.build();

			voArrayList.add(speTreeVo);
		}

		return voArrayList;
	}

	private List<SchoolSpeTreeVo> convertLevel2SpeTree(List<SpecialLevelIo> yanSchoolRecruits) {

		List<SchoolSpeTreeVo> voArrayList = new ArrayList<SchoolSpeTreeVo>();

		Map<String, List<SpecialLevelIo>> level2 = yanSchoolRecruits.stream()
				.sorted(Comparator.comparing(SpecialLevelIo::getLevel2Code))
				.collect(Collectors.groupingBy(SpecialLevelIo::getLevel2Code, LinkedHashMap::new, Collectors.toList()));
		for (Map.Entry<String, List<SpecialLevelIo>> entry : level2.entrySet()) {
			List<SpecialLevelIo> level2Value = entry.getValue();
			if (CollectionUtils.isEmpty(level2Value)) {
				continue;
			}
			SpecialLevelIo yanMasterSpecial = level2Value.get(0);
			level2Value = level2Value.stream().sorted(Comparator.comparing(SpecialLevelIo::getSpecialCode)).collect(Collectors.toList());
			List<SchoolSpeTreeVo> subList = new ArrayList<SchoolSpeTreeVo>();
			for (SpecialLevelIo yanMasterSpecial1 : level2Value) {
				subList.add(SchoolSpeTreeVo.builder().code(yanMasterSpecial1.getSpecialCode()).name(yanMasterSpecial1.getSpecialName()).build());
			}
			SchoolSpeTreeVo speTreeVo = SchoolSpeTreeVo.builder()
					.code(yanMasterSpecial.getLevel2Code())
					.name(yanMasterSpecial.getLevel2Name())
					.subTree(subList)
					.build();

			voArrayList.add(speTreeVo);
		}

		return voArrayList;
	}

	public List<YanMasterSpecialVo> listMasterSpe(ListMasterSpeQry qry) {

		LambdaQueryWrapper<YanMasterSpecial> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(Objects.nonNull(qry.getLevel1Code()), YanMasterSpecial::getLevel1Code, qry.getLevel1Code())
				.eq(Objects.nonNull(qry.getLevel2Code()), YanMasterSpecial::getLevel2Code, qry.getLevel2Code());
		if ("match".equals(qry.getQueryType())) {
			queryWrapper.like(Objects.nonNull(qry.getSpecialName()), YanMasterSpecial::getSpecialName, qry.getSpecialName());
		}else if ("recommend".equals(qry.getQueryType())) {
			queryWrapper.like(Objects.nonNull(qry.getSpecialName()), YanMasterSpecial::getSpecialName, qry.getSpecialName())
			.or().like(Objects.nonNull(qry.getSpecialName()), YanMasterSpecial::getInfo, qry.getSpecialName());
		}
		queryWrapper.eq(Objects.nonNull(qry.getLevel2Code()), YanMasterSpecial::getLevel2Code, qry.getLevel2Code());
		queryWrapper.eq(Objects.nonNull(qry.getLevel1Code()), YanMasterSpecial::getLevel1Code, qry.getLevel1Code());
		queryWrapper.eq(Objects.nonNull(qry.getSpecialCode()), YanMasterSpecial::getSpecialCode, qry.getSpecialCode());
		queryWrapper.in(Objects.nonNull(qry.getLevel2CodeList()), YanMasterSpecial::getLevel2Code, qry.getLevel2CodeList());
		queryWrapper.eq(Objects.nonNull(qry.getDegreeType()), YanMasterSpecial::getDegreeType, qry.getDegreeType());
		queryWrapper.eq(Objects.nonNull(qry.getDegreeTypeName()), YanMasterSpecial::getDegreeTypeName, qry.getDegreeTypeName());
		queryWrapper.eq(Objects.nonNull(qry.getSpecialName()), YanMasterSpecial::getSpecialName, qry.getSpecialName());

		List<YanMasterSpecialVo> yanMasterSpecialVos = this.baseMapper.listMasterSpecial(qry);
		yanMasterSpecialVos.forEach(x->{
			x.setCityContent(JSONObject.parseArray(x.getCityContentStr(), SpeWorkDetailIo.class));
			x.setIndustryContent(JSONObject.parseArray(x.getIndustryContentStr(), SpeWorkDetailIo.class));
			x.setSalaryContent(JSONObject.parseArray(x.getSalaryContentStr(), SpeWorkDetailIo.class));
			x.setCityContentStr(null);
			x.setIndustryContentStr(null);
			x.setSalaryContentStr(null);

		});
		return yanMasterSpecialVos;
	}

	public YanMasterSpecial saveMasterSpe(YanMasterSpecial cmd) {

		if (Objects.isNull(cmd.getSpecialId())) {
			this.baseMapper.insert(cmd);
		} else {
			YanMasterSpecial yanMasterSpecial = this.specialDetail(cmd.getSpecialId());
			Optional.ofNullable(cmd.getCityContent()).ifPresent(yanMasterSpecial::setCityContent);
			//Optional.ofNullable(cmd.getSpecialName()).ifPresent(yanMasterSpecial::setSpecialName);
			Optional.ofNullable(cmd.getIndustryContent()).ifPresent(yanMasterSpecial::setIndustryContent);
			Optional.ofNullable(cmd.getSalaryContent()).ifPresent(yanMasterSpecial::setSalaryContent);
			Optional.ofNullable(cmd.getWorkRemark()).ifPresent(yanMasterSpecial::setWorkRemark);
			Optional.ofNullable(cmd.getInfo()).ifPresent(yanMasterSpecial::setInfo);

			this.baseMapper.updateById(yanMasterSpecial);
			cmd = yanMasterSpecial;
		}
		return cmd;
	}

	public List<YanSpecialGjx> listSpecialGjx(String level1Code, String area, Integer year) {

		LambdaQueryWrapper<YanSpecialGjx> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(YanSpecialGjx::getCode, level1Code);
		queryWrapper.eq(YanSpecialGjx::getAreaType, area);
		queryWrapper.eq(Objects.nonNull(year), YanSpecialGjx::getYear, year);
		queryWrapper.orderByAsc(YanSpecialGjx::getYear);

		return yanSpecialGjxMapper.selectList(queryWrapper);
	}
}
